package com.zgzg.shop.pay.base.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;

/**
 * @Author: wangyy
 * @Date: 2023/3/16 14:51
 */
@Slf4j
public class Auth {
    public static final String UTF_8 = "UTF-8";
    public final String accessKey;
    private final SecretKeySpec secretKey;

    private Auth(String accessKey, SecretKeySpec secretKeySpec) {
        this.accessKey = accessKey;
        this.secretKey = secretKeySpec;
    }

    public static Auth create(String accessKey, String secretKey) throws UnsupportedEncodingException {
        if (StringUtils.isEmpty(accessKey) || StringUtils.isEmpty(secretKey)) {
            throw new IllegalArgumentException("empty key");
        }
        byte[] sk = utf8Bytes(secretKey);
        SecretKeySpec secretKeySpec = new SecretKeySpec(sk, "HmacSHA1");
        return new Auth(accessKey, secretKeySpec);
    }


    /**
     * 除GET其它方法签名
     *
     * @param url
     * @param method
     * @param contentType
     * @return
     * @throws UnsupportedEncodingException
     */
    public String authorization(String method, String url, String contentType, Long timeStack) throws UnsupportedEncodingException {
        return signRequestV2(url, method, contentType, timeStack);
    }

    /**
     * 生成GET方法签名
     *
     * @param path
     * @return
     * @throws UnsupportedEncodingException
     */
    public String authorization(String method, String path, Long timeStack) {
        try {
            return authorization(method, path, null, timeStack);
        } catch (Exception e) {
            log.debug("authorization error", e);
            return null;
        }
    }


    public static byte[] utf8Bytes(String data) throws UnsupportedEncodingException {
        return data.getBytes(UTF_8);
    }

    public String signRequestV2(String urlString, String method, String contentType, Long timeStack) throws UnsupportedEncodingException {
        return String.format("%s:%s:%s", this.accessKey, timeStack, digest(urlString, method, contentType, timeStack));
    }

    public String digest(String path, String method, String contentType, Long timeStack) throws UnsupportedEncodingException {
        Mac mac = createMac();
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("%s %s", method, path));
        if (timeStack != null) {
            sb.append(String.format("\ntimeStack: %s", timeStack));
        }
        if (contentType != null) {
            sb.append(String.format("\nContent-Type: %s", contentType));
        }
        mac.update(utf8Bytes(sb.toString()));
        String digest = Base64.encodeBase64URLSafeString(mac.doFinal());
        return digest;
    }

    private Mac createMac() {
        Mac mac;
        try {
            mac = Mac.getInstance("HmacSHA1");
            mac.init(secretKey);
        } catch (GeneralSecurityException e) {
            log.error("create mac erorr", e);
            throw new IllegalArgumentException(e);
        }
        return mac;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        String accessKey = "KyMQ6OSWG2o4DXrj";
        String secretKey = "vOoPnbcwYdtj8fKCT53ANi2VymaW6uX7SpzlMQIe";
        Auth auth = Auth.create(accessKey, secretKey);
        String token = auth.authorization("POST", "/tmy-cmc-globalmedia/openapi/v3/published/web/callback", System.currentTimeMillis());
        System.out.println(token);
    }
}
